
#include "UISystem.h"

#include <ALittleClient/ScheduleSystem/EventDefine.h>
#include <ALittleClient/ScriptSystem/ScriptSystem.h>
#include <ALittleClient/LogSystem/LogSystem.h>
#include <ALittleClient/FileSystem/FileSystem.h>
#include <ALittleClient/RenderSystem/RenderSystem.h>

#include "UIQuad.h"
#include "UIImage.h"
#include "UIDisplayView.h"

#include <SDL2/SDL_image.h>

namespace ALittle
{

UISystem::UISystem()
{ }

UISystem::~UISystem() {}

UISystem& UISystem::Instance()
{
	static UISystem instance;
	return instance;
}

void UISystem::Setup()
{
}

void UISystem::Shutdown()
{
	m_layer_list.RemoveAll();
}

void UISystem::RegisterToScript()
{
	g_ScriptSystem.RegisterClass2Script<UIDisplayObject>("GlobalUIDisplayObject");

	g_ScriptSystem.RegisterClass2Script<UIQuad>("GlobalUIQuad")
			.Constructor()
			.AddMemberFunction("SetX", &UIQuad::SetX)
			.AddMemberFunction("SetY", &UIQuad::SetY)
			.AddMemberFunction("SetWidth", &UIQuad::SetWidth)
			.AddMemberFunction("SetHeight", &UIQuad::SetHeight)
			.AddMemberFunction("SetRed", &UIQuad::SetRed)
			.AddMemberFunction("SetGreen", &UIQuad::SetGreen)
			.AddMemberFunction("SetBlue", &UIQuad::SetBlue)
			.AddMemberFunction("SetAlpha", &UIQuad::SetAlpha)
			.AddMemberFunction("SetVisible", &UIQuad::SetVisible);

	g_ScriptSystem.RegisterClass2Script<UIImage>("GlobalUIImage")
			.Constructor()
			.AddMemberFunction("SetX", &UIImage::SetX)
			.AddMemberFunction("SetY", &UIImage::SetY)
			.AddMemberFunction("SetWidth", &UIImage::SetWidth)
			.AddMemberFunction("SetHeight", &UIImage::SetHeight)
			.AddMemberFunction("SetRed", &UIImage::SetRed)
			.AddMemberFunction("SetGreen", &UIImage::SetGreen)
			.AddMemberFunction("SetBlue", &UIImage::SetBlue)
			.AddMemberFunction("SetAlpha", &UIImage::SetAlpha)
			.AddMemberFunction("SetTexture", &UIImage::SetTexture)
			.AddMemberFunction("SetTextureCoord", &UIImage::SetTextureCoord)
			.AddMemberFunction("SetVisible", &UIImage::SetVisible);

	g_ScriptSystem.RegisterClass2Script<UIDisplayObjects>("GlobalUIDisplayObjects")
			.Constructor()
			.AddMemberFunction("SetX", &UIDisplayObjects::SetX)
			.AddMemberFunction("SetY", &UIDisplayObjects::SetY)
			.AddMemberFunction("AddChild", &UIDisplayObjects::AddChild)
			.AddMemberFunction("RemoveChild", &UIDisplayObjects::RemoveChild)
			.AddMemberFunction("RemoveAll", &UIDisplayObjects::RemoveAll)
			.AddMemberFunction("SetVisible", &UIDisplayObjects::SetVisible)
			.AddMemberFunction("SetAngle", &UIDisplayObjects::SetAngle);

	g_ScriptSystem.RegisterClass2Script<UIDisplayView>("GlobalUIDisplayView")
			.Constructor()
			.AddMemberFunction("SetX", &UIDisplayView::SetX)
			.AddMemberFunction("SetY", &UIDisplayView::SetY)
			.AddMemberFunction("SetWidth", &UIDisplayView::SetWidth)
			.AddMemberFunction("SetHeight", &UIDisplayView::SetHeight)
			.AddMemberFunction("AddChild", &UIDisplayView::AddChild)
			.AddMemberFunction("RemoveChild", &UIDisplayView::RemoveChild)
			.AddMemberFunction("RemoveAll", &UIDisplayView::RemoveAll)
			.AddMemberFunction("SetVisible", &UIDisplayView::SetVisible);

	g_ScriptSystem.RegisterClass2Script<UISystem>("GlobalUISystem")
		.AddMemberFunction("AddLayer", &UISystem::AddLayer);

	g_ScriptSystem.SetValue("Global_UISystem", &g_UISystem);
}

void UISystem::AddLayer(UIDisplayObject* object)
{
	m_layer_list.AddChild(object);
}

void UISystem::Render()
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, g_RenderSystem.GetWindowWidth(), g_RenderSystem.GetWindowHeight(), 0, -1, 1);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	m_layer_list.Render();
}

void UISystem::CreateTexture(const char* path)
{
	g_FileSystem.LoadFile(path, this);
}

void UISystem::ReleaseTexture(GLuint resource)
{
	if (!resource) return;
	glDeleteTextures(1, &resource);
}

void UISystem::Notify(File* file)
{
	if (!file || file->GetContent() == NULL) return;

	SDL_RWops* mem = SDL_RWFromMem(file->GetContent(), file->GetSize());
	SDL_Surface* surface = IMG_Load_RW(mem, 0);
	SDL_FreeRW(mem);

	if (!surface)
	{
		ALITTLE_ERROR(SDL_GetError());
		return;
	}

	glEnable(GL_TEXTURE_2D);
	GLuint texture_id = 0;
	glGenTextures(1, &texture_id);

	glBindTexture(GL_TEXTURE_2D, texture_id);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	int mode = surface->format->BytesPerPixel == 4 ? GL_RGBA : GL_RGB;
	glTexImage2D(GL_TEXTURE_2D, 0, mode, surface->w, surface->h, 0, mode, GL_UNSIGNED_BYTE, surface->pixels);

	glDisable(GL_TEXTURE_2D);

	SDL_FreeSurface(surface);

	g_ScriptSystem.Invoke<void>("Global_AddTexture", file->GetPath().c_str(), texture_id);
}

} // ALittle
